package lock;

/**
 * ReentrantLock(重入锁)
 * 锁申请等待限时（tryLock）
 * 常，无法判断为什么一个线程迟迟拿不到锁。也许是因为产生了死锁，也许是产生了饥饿。
 * 但如果给定一个等待时间，让线程自动放弃，那么对系统来说是有意义的。可以使用 tryLock() 方法进行一次限时的等待。
 */

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockDemo3 implements Runnable {
    //声明一把锁，其中ReentrantLock（可重入的互斥锁）是Lock接口的一个实现
    public static ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
        try {
            if (lock.tryLock(5, TimeUnit.SECONDS)) {
                //Thread.sleep(4 * 1000);  //线程2可以等待4s后拿到锁
                Thread.sleep(6 * 1000);//线程2等待5分钟后，等待超时
            } else {
                System.out.println(Thread.currentThread().getName() + " get Lock Failed");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //查询当前线程是否保持此锁
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
                System.out.println(Thread.currentThread().getName() + "，lock解锁。");
            }
            System.out.println(Thread.currentThread().getName() + "，退出。");
        }
    }


    public static void main(String[] args) throws InterruptedException {
        /**
         * 在本例中，由于占用锁的线程会持有锁长达6秒，故另一个线程无法再5秒的等待时间内获得锁，因此请求锁会失败。
         */
        ReentrantLockDemo3 timeLock = new ReentrantLockDemo3();
        Thread thread1 = new Thread(timeLock, "线程1");
        Thread thread2 = new Thread(timeLock, "线程2");
        thread1.start();
        thread2.start();
    }

}

/*
ReentrantLock.tryLock()方法也可以不带参数直接运行。
这种情况下，当前线程会尝试获得锁，如果锁并未被其他线程占用，则申请锁成功，立即返回 true。
否则，申请失败，立即返回 false，当前线程不会进行等待。这种模式不会引起线程等待，因此也不会产生死锁。
 */